data <- fread('HomeSalesData.csv', encoding = 'UTF-8')
La descripción de las variables es la siguiente:
id: identificador para cada casa. date: fecha de venta de la casa. price: precio de venta de la casa. bedrooms: número de habitaciones. bathrooms: número de baños. sqft_living: pies cuadrados del interior de una casa. sqft_lot: pies cuadrados de terreno de una casa. floors: número de plantas de una casa. waterfront: variable dummy que vale 1 si la casa está enfrente del mar. view: índice de 0 a 4 indicando como de buenas son las vistas. condition: índice de 1 a 5 indicando como de buenas son las condiciones de las casas. grade: índice de 1 a 13 indicando el grado de construcción y diseño de la casa (de 1-3 mala construcción y diseño, 7 nivel medio de construcción y diseño y de 11-13 muy buena construcción y diseño). sqft_above: los pies cuadrados del espacio de la vivienda interior que está por encima del nivel del suelo. sqft_basement: pies cuadrados del sotano de una casa. yr_built: año de construcción de la casa. yr_renovated: año de renovación de la casa. zipcode: código postal de la casa. lat: latitud. long: longitud. sqft_living15: pies cuadrados del interior de las casas de los 15 vecinos más próximos. sqft_lot15: pies cuadrados del terreno de las casas de los 15 vecinos más próximos.
Vamos a hacer un pequeño análisis exploratorio para hacernos una idea de cómo se relacionan las variables de nuestro dataset. Previamente, observamos cómo son cada una de las variables por si tenemos que cambiar su clase.
## id date price
## Min. : 1000102 Length:21613 Min. : 75000
## 1st Qu.:2123049194 Class :character 1st Qu.: 321950
## Median :3904930410 Mode :character Median : 450000
## Mean :4580301520 Mean : 540088
## 3rd Qu.:7308900445 3rd Qu.: 645000
## Max. :9900000190 Max. :7700000
## bedrooms bathrooms sqft_living sqft_lot
## Min. : 0.000 Min. :0.000 Min. : 290 Min. : 520
## 1st Qu.: 3.000 1st Qu.:1.750 1st Qu.: 1427 1st Qu.: 5040
## Median : 3.000 Median :2.250 Median : 1910 Median : 7618
## Mean : 3.371 Mean :2.115 Mean : 2080 Mean : 15107
## 3rd Qu.: 4.000 3rd Qu.:2.500 3rd Qu.: 2550 3rd Qu.: 10688
## Max. :33.000 Max. :8.000 Max. :13540 Max. :1651359
## floors waterfront view condition
## Min. :1.000 Min. :0.000000 Min. :0.0000 Min. :1.000
## 1st Qu.:1.000 1st Qu.:0.000000 1st Qu.:0.0000 1st Qu.:3.000
## Median :1.500 Median :0.000000 Median :0.0000 Median :3.000
## Mean :1.494 Mean :0.007542 Mean :0.2343 Mean :3.409
## 3rd Qu.:2.000 3rd Qu.:0.000000 3rd Qu.:0.0000 3rd Qu.:4.000
## Max. :3.500 Max. :1.000000 Max. :4.0000 Max. :5.000
## grade sqft_above sqft_basement yr_built
## Min. : 1.000 Min. : 290 Min. : 0.0 Min. :1900
## 1st Qu.: 7.000 1st Qu.:1190 1st Qu.: 0.0 1st Qu.:1951
## Median : 7.000 Median :1560 Median : 0.0 Median :1975
## Mean : 7.657 Mean :1788 Mean : 291.5 Mean :1971
## 3rd Qu.: 8.000 3rd Qu.:2210 3rd Qu.: 560.0 3rd Qu.:1997
## Max. :13.000 Max. :9410 Max. :4820.0 Max. :2015
## yr_renovated zipcode lat long
## Min. : 0.0 Min. :98001 Min. :47.16 Min. :-122.5
## 1st Qu.: 0.0 1st Qu.:98033 1st Qu.:47.47 1st Qu.:-122.3
## Median : 0.0 Median :98065 Median :47.57 Median :-122.2
## Mean : 84.4 Mean :98078 Mean :47.56 Mean :-122.2
## 3rd Qu.: 0.0 3rd Qu.:98118 3rd Qu.:47.68 3rd Qu.:-122.1
## Max. :2015.0 Max. :98199 Max. :47.78 Max. :-121.3
## sqft_living15 sqft_lot15
## Min. : 399 Min. : 651
## 1st Qu.:1490 1st Qu.: 5100
## Median :1840 Median : 7620
## Mean :1987 Mean : 12768
## 3rd Qu.:2360 3rd Qu.: 10083
## Max. :6210 Max. :871200
## Classes 'data.table' and 'data.frame': 21613 obs. of 21 variables:
## $ id :integer64 7129300520 6414100192 5631500400 2487200875 1954400510 7237550310 1321400060 2008000270 ...
## $ date : chr "20141013T000000" "20141209T000000" "20150225T000000" "20141209T000000" ...
## $ price : num 221900 538000 180000 604000 510000 ...
## $ bedrooms : int 3 3 2 4 3 4 3 3 3 3 ...
## $ bathrooms : num 1 2.25 1 3 2 4.5 2.25 1.5 1 2.5 ...
## $ sqft_living : int 1180 2570 770 1960 1680 5420 1715 1060 1780 1890 ...
## $ sqft_lot : int 5650 7242 10000 5000 8080 101930 6819 9711 7470 6560 ...
## $ floors : num 1 2 1 1 1 1 2 1 1 2 ...
## $ waterfront : int 0 0 0 0 0 0 0 0 0 0 ...
## $ view : int 0 0 0 0 0 0 0 0 0 0 ...
## $ condition : int 3 3 3 5 3 3 3 3 3 3 ...
## $ grade : int 7 7 6 7 8 11 7 7 7 7 ...
## $ sqft_above : int 1180 2170 770 1050 1680 3890 1715 1060 1050 1890 ...
## $ sqft_basement: int 0 400 0 910 0 1530 0 0 730 0 ...
## $ yr_built : int 1955 1951 1933 1965 1987 2001 1995 1963 1960 2003 ...
## $ yr_renovated : int 0 1991 0 0 0 0 0 0 0 0 ...
## $ zipcode : int 98178 98125 98028 98136 98074 98053 98003 98198 98146 98038 ...
## $ lat : num 47.5 47.7 47.7 47.5 47.6 ...
## $ long : num -122 -122 -122 -122 -122 ...
## $ sqft_living15: int 1340 1690 2720 1360 1800 4760 2238 1650 1780 2390 ...
## $ sqft_lot15 : int 5650 7639 8062 5000 7503 101930 6819 9711 8113 7570 ...
## - attr(*, ".internal.selfref")=<externalptr>
data$yr_renovated <- as.factor(ifelse(is.na(data$yr_renovated), "", ifelse(data$yr_renovated== 0, 0, ifelse(data$yr_renovated < 1995, 1, 2))))
data$yr_built <- as.factor(ifelse(is.na(data$yr_built), "", ifelse(data$yr_built <= 1985, 0, ifelse(data$yr_built > 1985 & data$yr_built < 2010, 1, 2))))
#data$yr_renovated[is.na(data$yr_renovated)] <- "Ausente"
#data$yr_renovated <- as.factor(data$yr_renovated)
Hacemos algunas transformaciones a los datos para sacar variables categóricas de los mismos, que nos den algo más de información sobre el target.
En primer lugar vamos a limpiar la fecha y a ponerle una codificación buena:
clean_date <- function(df = data){
df$date <- gsub('T.*', "", df$date)
df$date <- as.Date(df$date, '%Y%m%d')
return(df)
}
df <- clean_date()
current_date <- Sys.Date()
df$antig <- current_date - df$date
Vamos a graficar todas las variables contra el precio de la casa, aunque antes partiremos los datos y todo este análisis lo haremos con los datos de train. Además, hacemos algunas transformaciones y le añadimos algunos datos más al modelo.
df$id <- NULL
df$month <- lubridate::month(df$date)
df$year <- lubridate::year(df$date)
df$price <- log(df$price)
df$zipcode <- NULL
df$date <- NULL
df$latlong <- df$lat * df$long
df$long2 <- df$long**2
df$lat2 <- df$lat**2
df$sqft_living15 <- log1p(df$sqft_living15)
df$sqft_lot15 <- log1p(df$sqft_lot15)
df$sqft_living <- log1p(df$sqft_living)
df$sqft_lot <- log1p(df$sqft_lot)
df$sqft_basement <- log1p(df$sqft_basement)
df$antig <- as.numeric(df$antig)
df$sqft_above <- log1p(df$sqft_above)
df$waterfront <- as.factor(df$waterfront)
df$view <- as.factor(df$view)
df$condition <- as.factor(df$condition)
df$month <- as.factor(df$month)
df$year <- as.factor(df$year)
library(magrittr)
##
## Attaching package: 'magrittr'
## The following object is masked from 'package:tidyr':
##
## extract
## The following object is masked from 'package:ggmap':
##
## inset
df$floors <- as.factor(df$floors)
#df$bedrooms <- as.factor(df$bedrooms)
df <- data.frame(df)
X = df[,colnames(df)!="price" & sapply(df, is.numeric)] %<>% scale()
X <- cbind(X, df[, sapply(df, is.factor)])
y <- df$price
total_df <- cbind(X, y)
index_train <- createDataPartition(y, p = 0.8, list = FALSE)
train <- total_df[index_train,]
test <- total_df[-index_train,]
nrow(train)
## [1] 17292
nrow(test)
## [1] 4321
Bien, como vemos, tenemos 17292 observaciones para entrenar y 4321 para testear nuestros resultados. Ahora vamos a hacer algunas visualizaciones para tratar de encontrar relaciones previas en los datos antes de comenzar a modelizar.
Vemos una relación lineal clarísima entre la variable sqft_living y price, no tanto entre el año y el precio, por lo que esperamos que esta variable sea menos explicativa. Respecto a la antiguedad, quizás hay demasiados datos para poder dilucir bien cuál es el efecto marginal de esta variable sobre el price.
En primer lugar vemos que existe una relación más o menos clara entre las variables price y sqft_lot; también vemos que sqft_lot está relacionado con sqft_above y sqft_basement, relaciones que vemos a partir del tamaño de los puntos y del color de los mismos. Además, podemos observar en el gráfico de arriba una cosa muy interesante, y es que las casas que tienen más metros cuadrados enla parte de arriba tienen un precio muy superior al resto de las casas; además estas suelen tener metros cuadrados en el basement. Aquí encontramos varias relaciones que pueden ser de interés para los modelos.
Entre la variable latlong y el precio (y) parece que claramente hay relación, negativa; esto significa que sí puede ser de utilidad haber incluido este cruce de las variables iniciales lat y long. Vemos además que las casas con mejor “grade” tienen un precio más alto, pues hay una clara división entre los puntos rojos y los verdes, los cuales representan precisamente esto, el grade de la casa en cuestión.
En este gráfico no se aprecian relaciones.
Se observa una relación positiva entre la variable latitud y el precio de las casas; además, podemos ver que las casas con precios más bajos son de la clase 0 principalmente de yr_builr; las observaciones que pertenecen a las clases 1 y 2 de esta variable tienen en general un precio más alto.
Vemos que las casas con un mayor número de baños tienen un precio más alto que las casas con menos baños. No se observa una relación del todo clara entre la longitud de la casa y el precio de la misma.
Apenas hay diferencias entre las casas que tienen y no tienen waterfront; aunque queda claro que las que no tienen waterfront son en general más baratas, las casas de precio más alto tienen la mayoría waterfront. Podemos ver además que existe una clara relación entre sqft_living15 y el precio de las casas. No se observan diferencias tan notables en el sqft_lot15, se podría decir que los que tienen valores más bajos en esta variable tienden a tener un precio medio, de exp(13) aproximadamente; a ambos lados de ese rango entre el 12.5 y el 14 los sqft_lot15 son más grandes.
Dedicaremos la mayor parte de nuestro tiempo al desarrollo de modelos predictivos para la variable Price, sin fijarnos tanto en la interpretabilidad de los modelos; sin embargo, dedicamos también un pequeño apartado aquí a los modelos explicativos. Para esta parte probaremos modelos muy sencillos, pues se interpretan bastante mejor. Aprovechamos para comentar aquí que no se observarán en las fórmulas demasiadas transformaciones con variables, esto es porque las variables que debían ser transformadas (al logaritmo por ejemplo), ya fueron transformadas anteriormente; se realizó un análisis previo, que no se enseña en este Markdown, en el que se vio cómo era el efecto de cada variable con la variable objetivo (el precio de las casas) y cómo sería en función de las diferentes transformaciones posibles.
linearM <- lm(y ~., data = train)
summary(linearM)
##
## Call:
## lm(formula = y ~ ., data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.1522 -0.1520 -0.0028 0.1444 1.2008
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.263e+01 7.917e-02 159.464 < 2e-16 ***
## bedrooms -1.843e-02 2.443e-03 -7.542 4.85e-14 ***
## bathrooms 2.473e-02 3.337e-03 7.411 1.31e-13 ***
## sqft_living 4.651e-02 9.474e-03 4.910 9.21e-07 ***
## sqft_lot 4.763e-02 4.810e-03 9.903 < 2e-16 ***
## grade 1.656e-01 3.276e-03 50.569 < 2e-16 ***
## sqft_above 1.066e-01 9.484e-03 11.242 < 2e-16 ***
## sqft_basement 4.220e-02 4.733e-03 8.914 < 2e-16 ***
## lat 4.307e+00 1.956e+00 2.202 0.027701 *
## long 3.523e+01 2.323e+00 15.161 < 2e-16 ***
## sqft_living15 7.925e-02 3.117e-03 25.426 < 2e-16 ***
## sqft_lot15 -3.104e-02 4.720e-03 -6.576 4.96e-11 ***
## antig 3.822e-02 2.443e-02 1.564 0.117811
## latlong -5.949e+01 1.989e+00 -29.904 < 2e-16 ***
## long2 1.433e+01 2.187e+00 6.555 5.72e-11 ***
## lat2 -5.703e+01 1.269e+00 -44.924 < 2e-16 ***
## floors1.5 7.447e-02 7.187e-03 10.362 < 2e-16 ***
## floors2 -7.929e-04 6.545e-03 -0.121 0.903574
## floors2.5 1.094e-01 2.154e-02 5.081 3.80e-07 ***
## floors3 -2.226e-02 1.351e-02 -1.647 0.099553 .
## floors3.5 1.645e-01 9.811e-02 1.676 0.093699 .
## waterfront1 4.115e-01 2.602e-02 15.817 < 2e-16 ***
## view1 1.566e-01 1.520e-02 10.306 < 2e-16 ***
## view2 1.087e-01 9.159e-03 11.865 < 2e-16 ***
## view3 1.843e-01 1.221e-02 15.093 < 2e-16 ***
## view4 2.519e-01 1.934e-02 13.027 < 2e-16 ***
## condition2 8.973e-02 5.420e-02 1.655 0.097841 .
## condition3 1.485e-01 5.027e-02 2.953 0.003148 **
## condition4 2.458e-01 5.030e-02 4.887 1.03e-06 ***
## condition5 3.308e-01 5.063e-02 6.533 6.63e-11 ***
## yr_built1 -1.242e-02 6.513e-03 -1.907 0.056600 .
## yr_built2 5.620e-02 1.008e-02 5.573 2.54e-08 ***
## yr_renovated1 7.548e-02 1.437e-02 5.252 1.52e-07 ***
## yr_renovated2 2.016e-01 1.215e-02 16.593 < 2e-16 ***
## month2 3.468e-02 1.313e-02 2.640 0.008297 **
## month3 7.175e-02 1.657e-02 4.330 1.50e-05 ***
## month4 1.003e-01 2.190e-02 4.578 4.72e-06 ***
## month5 1.241e-01 2.736e-02 4.537 5.75e-06 ***
## month6 1.477e-01 3.430e-02 4.305 1.68e-05 ***
## month7 1.551e-01 4.022e-02 3.855 0.000116 ***
## month8 1.643e-01 4.639e-02 3.541 0.000399 ***
## month9 1.671e-01 5.264e-02 3.173 0.001509 **
## month10 1.812e-01 5.905e-02 3.069 0.002152 **
## month11 2.014e-01 6.511e-02 3.092 0.001988 **
## month12 2.039e-01 7.122e-02 2.863 0.004197 **
## year2015 2.188e-01 7.769e-02 2.817 0.004859 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2393 on 17246 degrees of freedom
## Multiple R-squared: 0.7938, Adjusted R-squared: 0.7933
## F-statistic: 1476 on 45 and 17246 DF, p-value: < 2.2e-16
Como tenemos muchas variables, además de que bastantes de ellas son categóricas, el output es enorme. Empecemos diciendo que las variables que no parecen significativas a la hora de explicar el precio serían (cogemos 0.10 como significance level) la antiguedad de la casa, el nivel de pisos 2, así como el nivel 3.5 (con respecto al nivel 1, que es el ausente en la ecuación), el nivel 2 de condition, el nivel 2 de month ( es decir, que el pertenecer al mes 2 con respecto a pertenecer al mes 1 la oferta, no es significativa la diferencia sobre el precio). EL número de dormitorios está curiosamente inversamente relacionado con el precio, mientras que el número de baños afecta de forma positiva l mismo. Las variables sqft_living, sqft_lot, sqft_above, sqft_basement, sqft_living15, y sqft_lot15, que pasamos anteriormente a logaritmos, y que ya intuíamos que tendrían una relación con el precio por los gráficos que mostramos antes, tienen todas un efecto positivo sobre el precio excepto la última. Grade es una de las variales que mayor efecto tiene sobre el precio, cuando ésta aumenta en una unidad, el precio aumenta un 16%. La latitud y la longitud (especialmente ésta última) son significativas, y ambas se relacionan de forma positiva con el precio. Las interacciones que introdujimos de estas variables (para captar relaciones no lineales de la zona de las casas con el precio) también son todas significativas. El efecto de latlong sobre el precio es negativo, al igual que el de latitud al cuadrado, mientras que el de longitud al cuadrado es positivo. Tener waterfront, frente a no tenerlo, aumenta el precio de la vivienda. Los niveles que inventamos antes para factorizar los años de construcción y de renovación también son significativos. En general cuanto mayor es el nivel de la variable condition, mayor es el precio, con respecto a si fuera condition nivel 1. Algo parecido pasa con el mes del año; para cada nivel (excepto Febrero) el precio esperado de la casa aumenta con respecto a si la casa se vende en Enero. Vemos además que el \(R^2\) del ajuste es de 0.7929, mientras que el ajustado es de 0.7924; esto significa que en teoría explicamos el 79.24% de la varianza de la variable logprice. Además, la pequeña diferencia entre ambos es un indicador de que no tenemos demasiadas variables incluidas en el modelo, lo cual es bueno a la hora de no producir overfitting (y como dijimos antes, para explicar queremos modelos relativamente sencillos sin demasiadas variables, pues cuantas más tengamos y más interacciones existan entre ellas es más difícil dilucir cuál es el posible, atendiendo a la muestra de datos, efecto marginal de cada una de las variables explicativas sobre el logaritmo del precio).
Ahora probaremos a ajustar un lasso, para ver con cuántas variables se queda (qué betas no transforma a 0).
## [1] 0.7571921
## [1] 0 1 1 2 2 2 3 3 3 3 3 3 4 5 5 5 5 6 6 6 6 7 7
## [24] 8 9 9 9 9 9 9 10 11 11 11 11 12 12 14 15 16 16 16 16 16 16 16
## [47] 17 17 17 17 17 18 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19
## [70] 19 19 19 19 19
Aquí vemos el \(R^2\) que alcanza la ElasticNet al terminar de optimizarse. Como le hemos puesto \(\alpha = 1\), es una penalización Lasso en su totalidad. Vemos que se ajusta un poco peor que el modelo anterior lineal sin penalización que mostrábamos, esto era de esperar pues estamos forzando al modelo a prescindir de algunas de sus variables. Como vemos, el modelo se acaba quedando con 19 variables, en lugar de las 23 que tenía antes. Este podría ser un mejor modelo para explicar en el sentido de que al eliminar alunas de las variables quitamos algo de ruido y podemos entender mejor qué factores, qué aspectos de una casa o de su entorno hacen que su precio sea elevado. Las variables que antes estaba en la frontera de ser o no rechazadas son las que probablemente el modelo haya decidido eliminar.
## Linear Regression with Forward Selection
##
## 17292 samples
## 23 predictor
##
## Pre-processing: scaled (45), centered (45)
## Resampling: Cross-Validated (5 fold, repeated 2 times)
## Summary of sample sizes: 13833, 13834, 13834, 13834, 13833, 13833, ...
## Resampling results across tuning parameters:
##
## nvmax RMSE Rsquared MAE
## 5 0.2731265 0.7308934 0.2099447
## 6 0.2675477 0.7417907 0.2056570
## 7 0.2647858 0.7470922 0.2048084
## 8 0.2621159 0.7521496 0.2017188
## 9 0.2552926 0.7648459 0.1965838
## 10 0.2525329 0.7699114 0.1945036
## 11 0.2511455 0.7724295 0.1934588
## 12 0.2494679 0.7754614 0.1919740
## 13 0.2483092 0.7775385 0.1909891
## 14 0.2472359 0.7794649 0.1900500
## 15 0.2458978 0.7818341 0.1889754
## 16 0.2449774 0.7834610 0.1882359
## 17 0.2440963 0.7850242 0.1875947
## 18 0.2437998 0.7855436 0.1875351
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 18.
## (Intercept) sqft_living grade sqft_above lat
## 13.04688429 0.12840609 0.17392637 0.03460888 4.20789286
## long sqft_living15 latlong lat2 floors1.5
## 20.64413307 0.07458741 -59.13078483 -56.57403941 0.02188742
## waterfront1 view1 view2 view3 view4
## 0.03855218 0.02094126 0.02574651 0.03212396 0.03259102
## condition3 condition5 yr_renovated2 year2015
## -0.04265777 0.02395394 0.03247954 0.02373893
## RMSE Rsquared MAE
## 1.898782e+05 7.570287e-01 1.034859e+05
Como vemos, de momento la predicción no es del todo correcta, pues nos equivocamos de media en casi 19,000$. Aún así, vemos que los valores predichos y los reales no están tan lejos los unos de los otros.
Probamos ahora con un backward selection, metiéndole de nuevo todas las variables.
## Linear Regression with Backwards Selection
##
## 17292 samples
## 23 predictor
##
## Pre-processing: scaled (45), centered (45)
## Resampling: Cross-Validated (5 fold, repeated 2 times)
## Summary of sample sizes: 13833, 13834, 13832, 13834, 13835, 13832, ...
## Resampling results across tuning parameters:
##
## nvmax RMSE Rsquared MAE
## 5 0.2877149 0.7013867 0.2223621
## 6 0.2708357 0.7353529 0.2061225
## 7 0.2642485 0.7480943 0.2022768
## 8 0.2578213 0.7601973 0.1990380
## 9 0.2545177 0.7663141 0.1962880
## 10 0.2510372 0.7726339 0.1936071
## 11 0.2486378 0.7769653 0.1917033
## 12 0.2473439 0.7792697 0.1907514
## 13 0.2461858 0.7813265 0.1899628
## 14 0.2452963 0.7829065 0.1892086
## 15 0.2441301 0.7849757 0.1882960
## 16 0.2434778 0.7861186 0.1876593
## 17 0.2426045 0.7876464 0.1868338
## 18 0.2424801 0.7878685 0.1869229
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 18.
## (Intercept) sqft_lot grade sqft_above sqft_basement
## 13.04688429 0.01602891 0.17172144 0.15638782 0.06770638
## long sqft_living15 latlong lat2 floors1.5
## 22.33683887 0.07454661 -63.97647659 -56.67370690 0.01947767
## waterfront1 view1 view2 view3 view4
## 0.03824735 0.01957848 0.02372018 0.03039553 0.03128652
## condition4 condition5 yr_renovated2 year2015
## 0.04088408 0.04931686 0.03244478 0.02379902
## RMSE Rsquared MAE
## 1.888981e+05 7.579709e-01 1.034427e+05
Vemos que la predicción ahora mejora ligeramente, sin grandes resultados pero desde luego mejor que los que estábamos obteniendo con forward.
Vamos a hacer ahora un leapregression; le aumentamos el número de variables máximas a 21:
leap <- train(form, data = train,
method = "leapSeq",
preProc=c('scale', 'center'),
tuneGrid = expand.grid(nvmax = 5:21),
trControl = control)
leap
## Linear Regression with Stepwise Selection
##
## 17292 samples
## 23 predictor
##
## Pre-processing: scaled (45), centered (45)
## Resampling: Cross-Validated (5 fold, repeated 2 times)
## Summary of sample sizes: 13832, 13834, 13835, 13834, 13833, 13834, ...
## Resampling results across tuning parameters:
##
## nvmax RMSE Rsquared MAE
## 5 0.2708300 0.7353578 0.2059859
## 6 0.2636966 0.7491074 0.2018670
## 7 0.2585844 0.7587221 0.1994317
## 8 0.2535961 0.7679277 0.1955893
## 9 0.2513900 0.7719347 0.1937539
## 10 0.2503990 0.7737342 0.1928616
## 11 0.2494988 0.7753629 0.1919438
## 12 0.2483953 0.7773540 0.1910489
## 13 0.2504559 0.7731727 0.1928323
## 14 0.2495297 0.7749480 0.1918984
## 15 0.2449799 0.7834541 0.1883447
## 16 0.2439116 0.7853413 0.1875522
## 17 0.2429733 0.7869903 0.1870427
## 18 0.2427941 0.7873023 0.1869760
## 19 0.2422696 0.7882188 0.1866531
## 20 0.2468712 0.7798521 0.1897096
## 21 0.2417682 0.7890901 0.1861533
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 21.
plot(leap)
# which variables are selected?
coef(leap$finalModel, leap$bestTune$nvmax)
## (Intercept) sqft_lot grade sqft_above sqft_basement
## 13.04688429 0.04665416 0.17058244 0.15255669 0.06654217
## long sqft_living15 sqft_lot15 latlong long2
## 37.51700545 0.08043925 -0.03035628 -63.30096471 15.41805109
## lat2 floors1.5 waterfront1 view1 view2
## -56.07302902 0.01822778 0.03846261 0.01922551 0.02291932
## view3 view4 condition4 condition5 yr_built2
## 0.02950573 0.03077086 0.04411799 0.05123427 0.01559638
## yr_renovated2 year2015
## 0.03341269 0.02394697
test_results$leap<- exp(predict(leap, test))
postResample(pred = test_results$leap, obs = test_results$price)
## RMSE Rsquared MAE
## 1.880474e+05 7.607211e-01 1.029118e+05
rmse = sqrt(mean(test_results$leap - test_results$price)^2)
ggplot(test_results, aes(x = leap, y = price)) +
geom_point() +
geom_smooth(method = "lm", se = F) +
geom_text(aes(label =paste("RMSE=", round(rmse, 3)), x = 1e+06, y = 4e+06))
Seguimos mejorando la predicción con respecto a los dos modelos anteriores. Parece que lo óptimo es incluir 21 variables, mejor que 18 como en el caso anterior. Como vemos que al dejar al modelo tener más variables las coge (esto significa que añadiendo más variables mejora el AIC), vamos a dejar de limitarle a tener un número máximo de variables, pues el objetivo aquí es predecir bien.
Lo siguiente que probaremos será una Ridge Regression; es decir, una regresión múltiple que cuenta con un término adicional que penaliza la inclusión de muchas variables (evitando así el overfitting).
## Ridge Regression
##
## 17292 samples
## 23 predictor
##
## Pre-processing: scaled (45), centered (45)
## Resampling: Cross-Validated (5 fold, repeated 2 times)
## Summary of sample sizes: 13833, 13834, 13835, 13833, 13833, 13834, ...
## Resampling results across tuning parameters:
##
## lambda RMSE Rsquared MAE
## 0.000000000 0.2397383 0.7925854 0.1843796
## 0.005263158 0.2567001 0.7622119 0.1988953
## 0.010526316 0.2567471 0.7621533 0.1989267
## 0.015789474 0.2568002 0.7621008 0.1989684
## 0.021052632 0.2568646 0.7620446 0.1990193
## 0.026315789 0.2569410 0.7619837 0.1990795
## 0.031578947 0.2570295 0.7619181 0.1991481
## 0.036842105 0.2571297 0.7618485 0.1992263
## 0.042105263 0.2572414 0.7617751 0.1993136
## 0.047368421 0.2573645 0.7616986 0.1994100
## 0.052631579 0.2574986 0.7616192 0.1995142
## 0.057894737 0.2576436 0.7615374 0.1996251
## 0.063157895 0.2577993 0.7614533 0.1997451
## 0.068421053 0.2579656 0.7613673 0.1998735
## 0.073684211 0.2581422 0.7612795 0.2000116
## 0.078947368 0.2583291 0.7611901 0.2001593
## 0.084210526 0.2585262 0.7610993 0.2003154
## 0.089473684 0.2587332 0.7610072 0.2004794
## 0.094736842 0.2589502 0.7609139 0.2006510
## 0.100000000 0.2591768 0.7608195 0.2008309
##
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was lambda = 0.
## RMSE Rsquared MAE
## 1.804914e+05 7.797715e-01 1.012362e+05
Vemos que la regresión Ridge mejora aún más la predicción, bajando ya de los 18000 dólares de media del error a 17634.573. Lo curioso sin embargo es que \(\lambda = 0\), es decir, que lo ideal en teoría, a juzgar por la optimización del modelo Ridge, es no penalizar en absoluto a las \(\beta\).
## [1] 0
Lo siguiente que vamos a hacer es añadir variables; esto lo haremos metiendo en la fórmula algunas interacciones entre variables; haremos esto con una Elastic Net que nos permita quedarnos sólo con algunas betas.
form <- y ~ . + bedrooms:bathrooms + sqft_living:sqft_lot:sqft_above:sqft_lot15:sqft_living15:sqft_basement + grade:latlong + grade:sqft_living
grid = expand.grid(alpha = seq(0, .2, 0.01), lambda = seq(0, .1, 0.01))
elasticnet <- train(form, data = train,
method='glmnet',
preProc=c('scale','center'),
tuneGrid = grid,
trControl=control)
## glmnet
##
## 17292 samples
## 23 predictor
##
## Pre-processing: scaled (49), centered (49)
## Resampling: Cross-Validated (5 fold, repeated 2 times)
## Summary of sample sizes: 13832, 13833, 13834, 13834, 13835, 13835, ...
## Resampling results across tuning parameters:
##
## alpha lambda RMSE Rsquared MAE
## 0.00 0.00 0.2550886 0.7655977 0.1980047
## 0.00 0.01 0.2550886 0.7655977 0.1980047
## 0.00 0.02 0.2550886 0.7655977 0.1980047
## 0.00 0.03 0.2550886 0.7655977 0.1980047
## 0.00 0.04 0.2551629 0.7655172 0.1980825
## 0.00 0.05 0.2554323 0.7652325 0.1983615
## 0.00 0.06 0.2557288 0.7649361 0.1986619
## 0.00 0.07 0.2560512 0.7646273 0.1989828
## 0.00 0.08 0.2563935 0.7643130 0.1993235
## 0.00 0.09 0.2567565 0.7639914 0.1996824
## 0.00 0.10 0.2571368 0.7636662 0.2000550
## 0.01 0.00 0.2545307 0.7662923 0.1973354
## 0.01 0.01 0.2546099 0.7661697 0.1974590
## 0.01 0.02 0.2547808 0.7659443 0.1976844
## 0.01 0.03 0.2550062 0.7656771 0.1979538
## 0.01 0.04 0.2552797 0.7653728 0.1982521
## 0.01 0.05 0.2555892 0.7650491 0.1985756
## 0.01 0.06 0.2559288 0.7647129 0.1989218
## 0.01 0.07 0.2562935 0.7643703 0.1992881
## 0.01 0.08 0.2566835 0.7640181 0.1996725
## 0.01 0.09 0.2570935 0.7636632 0.2000685
## 0.01 0.10 0.2575247 0.7633013 0.2004827
## 0.02 0.00 0.2545112 0.7663232 0.1973195
## 0.02 0.01 0.2546303 0.7661374 0.1974977
## 0.02 0.02 0.2548247 0.7658831 0.1977619
## 0.02 0.03 0.2550932 0.7655584 0.1980823
## 0.02 0.04 0.2554092 0.7652045 0.1984275
## 0.02 0.05 0.2557611 0.7648371 0.1987944
## 0.02 0.06 0.2561452 0.7644599 0.1991820
## 0.02 0.07 0.2565631 0.7640656 0.1995972
## 0.02 0.08 0.2570090 0.7636602 0.2000306
## 0.02 0.09 0.2574798 0.7632473 0.2004808
## 0.02 0.10 0.2579759 0.7628239 0.2009511
## 0.03 0.00 0.2545121 0.7663202 0.1973252
## 0.03 0.01 0.2546482 0.7661097 0.1975337
## 0.03 0.02 0.2548801 0.7658013 0.1978479
## 0.03 0.03 0.2551889 0.7654246 0.1982131
## 0.03 0.04 0.2555481 0.7650205 0.1985995
## 0.03 0.05 0.2559484 0.7646004 0.1990096
## 0.03 0.06 0.2563870 0.7641630 0.1994527
## 0.03 0.07 0.2568535 0.7637263 0.1999179
## 0.03 0.08 0.2573587 0.7632650 0.2004078
## 0.03 0.09 0.2578988 0.7627811 0.2009190
## 0.03 0.10 0.2584550 0.7623090 0.2014449
## 0.04 0.00 0.2545092 0.7663265 0.1973296
## 0.04 0.01 0.2546675 0.7660798 0.1975685
## 0.04 0.02 0.2549423 0.7657072 0.1979368
## 0.04 0.03 0.2552928 0.7652766 0.1983444
## 0.04 0.04 0.2557004 0.7648137 0.1987733
## 0.04 0.05 0.2561461 0.7643464 0.1992343
## 0.04 0.06 0.2566272 0.7638770 0.1997240
## 0.04 0.07 0.2571606 0.7633662 0.2002518
## 0.04 0.08 0.2577408 0.7628186 0.2008101
## 0.04 0.09 0.2583402 0.7622847 0.2013784
## 0.04 0.10 0.2589500 0.7617822 0.2019436
## 0.05 0.00 0.2545177 0.7663088 0.1973398
## 0.05 0.01 0.2546886 0.7660467 0.1976076
## 0.05 0.02 0.2550045 0.7656139 0.1980236
## 0.05 0.03 0.2554049 0.7651154 0.1984732
## 0.05 0.04 0.2558597 0.7645969 0.1989547
## 0.05 0.05 0.2563397 0.7641073 0.1994576
## 0.05 0.06 0.2568896 0.7635561 0.2000148
## 0.05 0.07 0.2575008 0.7629499 0.2006128
## 0.05 0.08 0.2581347 0.7623581 0.2012203
## 0.05 0.09 0.2587833 0.7617952 0.2018206
## 0.05 0.10 0.2594582 0.7612349 0.2024317
## 0.06 0.00 0.2545161 0.7663142 0.1973448
## 0.06 0.01 0.2547148 0.7660047 0.1976500
## 0.06 0.02 0.2550758 0.7655050 0.1981128
## 0.06 0.03 0.2555308 0.7649305 0.1986129
## 0.06 0.04 0.2560071 0.7644071 0.1991266
## 0.06 0.05 0.2565504 0.7638414 0.1996969
## 0.06 0.06 0.2571731 0.7632000 0.2003225
## 0.06 0.07 0.2578457 0.7625299 0.2009758
## 0.06 0.08 0.2585344 0.7618943 0.2016188
## 0.06 0.09 0.2592488 0.7612728 0.2022647
## 0.06 0.10 0.2600084 0.7606199 0.2029403
## 0.07 0.00 0.2545346 0.7662883 0.1973442
## 0.07 0.01 0.2547430 0.7659592 0.1976923
## 0.07 0.02 0.2551510 0.7653894 0.1981990
## 0.07 0.03 0.2556423 0.7647733 0.1987428
## 0.07 0.04 0.2561619 0.7642064 0.1993092
## 0.07 0.05 0.2567763 0.7635503 0.1999490
## 0.07 0.06 0.2574690 0.7628243 0.2006350
## 0.07 0.07 0.2581938 0.7621101 0.2013257
## 0.07 0.08 0.2589424 0.7614243 0.2020059
## 0.07 0.09 0.2597419 0.7607045 0.2027170
## 0.07 0.10 0.2605974 0.7599347 0.2034714
## 0.08 0.00 0.2545358 0.7662831 0.1973539
## 0.08 0.01 0.2547731 0.7659100 0.1977356
## 0.08 0.02 0.2552295 0.7652680 0.1982871
## 0.08 0.03 0.2557473 0.7646304 0.1988671
## 0.08 0.04 0.2563281 0.7639867 0.1995018
## 0.08 0.05 0.2570143 0.7632384 0.2002088
## 0.08 0.06 0.2577708 0.7624406 0.2009444
## 0.08 0.07 0.2585461 0.7616895 0.2016615
## 0.08 0.08 0.2593746 0.7609133 0.2024026
## 0.08 0.09 0.2602737 0.7600687 0.2031942
## 0.08 0.10 0.2612336 0.7591644 0.2040370
## 0.09 0.00 0.2545481 0.7662637 0.1973606
## 0.09 0.01 0.2548028 0.7658617 0.1977770
## 0.09 0.02 0.2553173 0.7651300 0.1983826
## 0.09 0.03 0.2558582 0.7644794 0.1989993
## 0.09 0.04 0.2565029 0.7637524 0.1997000
## 0.09 0.05 0.2572614 0.7629113 0.2004701
## 0.09 0.06 0.2580681 0.7620703 0.2012367
## 0.09 0.07 0.2589131 0.7612469 0.2020002
## 0.09 0.08 0.2598359 0.7603508 0.2028183
## 0.09 0.09 0.2608352 0.7593750 0.2036937
## 0.09 0.10 0.2619062 0.7583215 0.2046301
## 0.10 0.00 0.2545486 0.7662626 0.1973660
## 0.10 0.01 0.2548337 0.7658118 0.1978171
## 0.10 0.02 0.2553997 0.7650018 0.1984775
## 0.10 0.03 0.2559741 0.7643209 0.1991352
## 0.10 0.04 0.2566877 0.7635030 0.1999047
## 0.10 0.05 0.2575135 0.7625775 0.2007265
## 0.10 0.06 0.2583696 0.7616981 0.2015222
## 0.10 0.07 0.2592999 0.7607690 0.2023522
## 0.10 0.08 0.2603212 0.7597442 0.2032480
## 0.10 0.09 0.2614315 0.7586172 0.2042175
## 0.10 0.10 0.2626110 0.7574175 0.2052420
## 0.11 0.00 0.2545614 0.7662428 0.1973732
## 0.11 0.01 0.2548679 0.7657560 0.1978590
## 0.11 0.02 0.2554695 0.7648992 0.1985613
## 0.11 0.03 0.2560945 0.7641556 0.1992769
## 0.11 0.04 0.2568811 0.7632378 0.2001136
## 0.11 0.05 0.2577636 0.7622521 0.2009728
## 0.11 0.06 0.2586826 0.7613077 0.2018114
## 0.11 0.07 0.2597056 0.7602575 0.2027135
## 0.11 0.08 0.2608372 0.7590812 0.2037018
## 0.11 0.09 0.2620617 0.7577962 0.2047708
## 0.11 0.10 0.2633322 0.7564885 0.2058597
## 0.12 0.00 0.2545531 0.7662598 0.1973669
## 0.12 0.01 0.2549048 0.7656955 0.1979030
## 0.12 0.02 0.2555371 0.7648021 0.1986449
## 0.12 0.03 0.2562196 0.7639827 0.1994210
## 0.12 0.04 0.2570792 0.7629659 0.2003208
## 0.12 0.05 0.2580098 0.7619379 0.2012101
## 0.12 0.06 0.2590107 0.7608916 0.2021068
## 0.12 0.07 0.2601377 0.7597006 0.2030957
## 0.12 0.08 0.2613803 0.7583707 0.2041819
## 0.12 0.09 0.2627134 0.7569399 0.2053374
## 0.12 0.10 0.2640469 0.7555797 0.2064583
## 0.13 0.00 0.2545441 0.7662742 0.1973576
## 0.13 0.01 0.2549446 0.7656298 0.1979485
## 0.13 0.02 0.2556048 0.7647058 0.1987285
## 0.13 0.03 0.2563529 0.7637975 0.1995714
## 0.13 0.04 0.2572793 0.7626932 0.2005243
## 0.13 0.05 0.2582614 0.7616162 0.2014454
## 0.13 0.06 0.2593558 0.7604458 0.2024156
## 0.13 0.07 0.2605900 0.7591079 0.2034970
## 0.13 0.08 0.2619452 0.7576197 0.2046782
## 0.13 0.09 0.2633580 0.7560986 0.2058862
## 0.13 0.10 0.2647457 0.7547120 0.2070280
## 0.14 0.00 0.2545393 0.7662810 0.1973621
## 0.14 0.01 0.2549850 0.7655630 0.1979945
## 0.14 0.02 0.2556769 0.7646023 0.1988166
## 0.14 0.03 0.2564877 0.7636072 0.1997218
## 0.14 0.04 0.2574824 0.7624153 0.2007293
## 0.14 0.05 0.2585243 0.7612781 0.2016842
## 0.14 0.06 0.2597173 0.7599741 0.2027399
## 0.14 0.07 0.2610687 0.7584673 0.2039215
## 0.14 0.08 0.2625203 0.7568516 0.2051793
## 0.14 0.09 0.2639795 0.7553134 0.2064028
## 0.14 0.10 0.2654350 0.7538686 0.2075879
## 0.15 0.00 0.2545370 0.7662848 0.1973620
## 0.15 0.01 0.2550255 0.7654964 0.1980400
## 0.15 0.02 0.2557526 0.7644938 0.1989074
## 0.15 0.03 0.2566318 0.7634020 0.1998783
## 0.15 0.04 0.2576770 0.7621580 0.2009173
## 0.15 0.05 0.2587976 0.7609220 0.2019321
## 0.15 0.06 0.2600991 0.7594652 0.2030800
## 0.15 0.07 0.2615614 0.7577980 0.2043558
## 0.15 0.08 0.2631022 0.7560745 0.2056769
## 0.15 0.09 0.2646008 0.7545350 0.2069118
## 0.15 0.10 0.2661239 0.7530340 0.2081553
## 0.16 0.00 0.2545475 0.7662697 0.1973684
## 0.16 0.01 0.2550683 0.7654256 0.1980866
## 0.16 0.02 0.2558303 0.7643815 0.1989988
## 0.16 0.03 0.2567777 0.7631946 0.2000344
## 0.16 0.04 0.2578733 0.7619001 0.2011034
## 0.16 0.05 0.2590840 0.7605440 0.2021910
## 0.16 0.06 0.2604974 0.7589248 0.2034338
## 0.16 0.07 0.2620677 0.7571071 0.2047999
## 0.16 0.08 0.2636582 0.7553558 0.2061415
## 0.16 0.09 0.2652245 0.7537567 0.2074215
## 0.16 0.10 0.2668266 0.7521725 0.2087384
## 0.17 0.00 0.2545455 0.7662731 0.1973598
## 0.17 0.01 0.2551131 0.7653511 0.1981347
## 0.17 0.02 0.2559063 0.7642729 0.1990890
## 0.17 0.03 0.2569281 0.7629794 0.2001932
## 0.17 0.04 0.2580722 0.7616394 0.2012891
## 0.17 0.05 0.2593829 0.7601422 0.2024612
## 0.17 0.06 0.2609120 0.7583530 0.2038026
## 0.17 0.07 0.2625871 0.7563907 0.2052509
## 0.17 0.08 0.2642003 0.7546683 0.2065891
## 0.17 0.09 0.2658406 0.7529969 0.2079332
## 0.17 0.10 0.2675421 0.7512874 0.2093351
## 0.18 0.00 0.2545471 0.7662711 0.1973631
## 0.18 0.01 0.2551583 0.7652762 0.1981832
## 0.18 0.02 0.2559870 0.7641565 0.1991837
## 0.18 0.03 0.2570759 0.7627714 0.2003473
## 0.18 0.04 0.2582792 0.7613644 0.2014797
## 0.18 0.05 0.2596968 0.7597131 0.2027430
## 0.18 0.06 0.2613479 0.7577419 0.2041883
## 0.18 0.07 0.2630675 0.7557576 0.2056570
## 0.18 0.08 0.2647492 0.7539713 0.2070409
## 0.18 0.09 0.2664664 0.7522184 0.2084555
## 0.18 0.10 0.2682628 0.7503926 0.2099325
## 0.19 0.00 0.2545397 0.7662829 0.1973715
## 0.19 0.01 0.2552045 0.7651993 0.1982344
## 0.19 0.02 0.2560703 0.7640353 0.1992792
## 0.19 0.03 0.2572244 0.7625629 0.2005003
## 0.19 0.04 0.2584958 0.7610731 0.2016776
## 0.19 0.05 0.2600236 0.7592600 0.2030337
## 0.19 0.06 0.2617806 0.7571383 0.2045657
## 0.19 0.07 0.2635501 0.7551229 0.2060615
## 0.19 0.08 0.2652916 0.7532912 0.2074926
## 0.19 0.09 0.2671089 0.7514092 0.2089912
## 0.19 0.10 0.2690028 0.7494637 0.2105441
## 0.20 0.00 0.2545403 0.7662830 0.1973744
## 0.20 0.01 0.2552515 0.7651213 0.1982865
## 0.20 0.02 0.2561556 0.7639109 0.1993746
## 0.20 0.03 0.2573702 0.7623611 0.2006456
## 0.20 0.04 0.2587220 0.7607647 0.2018830
## 0.20 0.05 0.2603646 0.7587810 0.2033372
## 0.20 0.06 0.2622212 0.7565215 0.2049476
## 0.20 0.07 0.2640235 0.7545123 0.2064542
## 0.20 0.08 0.2658449 0.7525904 0.2079562
## 0.20 0.09 0.2677517 0.7506010 0.2095247
## 0.20 0.10 0.2697193 0.7485895 0.2111401
##
## RMSE was used to select the optimal model using the smallest value.
## The final values used for the model were alpha = 0.04 and lambda = 0.
## RMSE Rsquared MAE
## 1.878140e+05 7.497623e-01 1.108452e+05
Como vemos, el modelo se ajusta algo peor cuando se regulariza en exceso, como vemos en el segundo de los dos gráficos superiores; en él se puede apreciar como claramente cuanto mayor es la proporción de penalización del tipo Norma 1 (valor absoluto) con respecto a la proporción de Norma 2 (cuadrado) peor es el modelo, en el sentido de que tiene un error mayor.
Adicionalmente, probaremos ahora con PCR y con PLS, otros dos métodos que utilizan técnicas de reducción de la dimensión con el objetivo de servir de regularizador.
## RMSE Rsquared MAE
## 3.225238e+05 4.555277e-01 1.258178e+05
Como vemos, el resultado es algo mejor que utilizando todas las variables, como vemos por el RMSE en el test, pues este es inferior al que habíamos obtenido antes. Vemos que hay una predicción que se le fue muchísimo de las manos, un claro outlier. Seguramente si elimináramos esa observación (aparte de que el gráfico sería más agradable a la vista) el ajuste sería mucho mejor, y el RMSE bajaría incluso más. Los errores grandes tienen un efecto fuerte sobre el MSE, y al hacer la raíz cuadrada de este algo se pueden disipar esos efectos, pero no del todo. Una métrica como el Median Absolute Error podría ser más informativa en casos en los que tenemos algunos claros outliers, pues es una métrica robusta frente a los mismos.
Probamos ahora con PLS (Partial Least Squares), que diseña los componentes con un poco más de criterio, poniéndolos en orden según el efecto que estos tienen sobre la variable objetivo; esto permite que el modelo capte mucho mejor la información útil (en teoría) que los componentes principales sin más.
## RMSE Rsquared MAE
## 1.876621e+05 7.500687e-01 1.108063e+05
Vemos que empeora, en términos de RMSE, los resultados obtenidos por el método PCR. No es lo que esperábamos, desde luego, pero los datos han hablado. Mejora, de todas formas, las predicciones realizadas por Ridge y por los otros métodos de regresión que vimos anteriormente.
Vamos a probar, además de los modelos que hemos probado ya, algunos modelos más avanzados de Machine Learning, para comparar esas predicciones con las obtenidas hasta ahora. Para ello utilizaremos Python y el paquete sklearn, pues es infinitamente más rápido que caret. Importaremos desde R un csv con los resultados de las predicciones de un Random Forest y un XGBoost y finalizaremos el análisis de los modelos predictivos.
Como tenemos la partición de train y test ya hecha, vamos a sacar esto a un csv para leerlo desde Python:
write.csv(train, 'train.csv', row.names = F, col.names = T, fileEncoding = 'utf-8', sep = ',')
## Warning in write.csv(train, "train.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'col.names' ignored
## Warning in write.csv(train, "train.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'sep' ignored
write.csv(test, 'test.csv', row.names = F, col.names = T, fileEncoding = 'utf-8', sep = ',')
## Warning in write.csv(test, "test.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'col.names' ignored
## Warning in write.csv(test, "test.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'sep' ignored
rf <- read.csv('preds_rf.txt', fileEncoding = 'utf-8', header = F)
xgb <- read.csv('preds_xgb.txt', fileEncoding = 'utf-8', header = F)
rmse = sqrt(mean(test_results$price - test_results$rf)^2)
ggplot(test_results, aes(x = rf, y = price)) +
geom_point() +
geom_smooth(method = "lm", se = F) +
geom_text(aes(label =paste("RMSE=", round(rmse, 3)), x = 1e+06, y = 4e+06))
Vaya, pues curiosamente el Random Forest predice bastante peor que los modelos lineales que utilizamos anteriormente. Parece tener un pequeño sesgo, predice precios más bajos de lo que suelen ser, especialmente para las casas de mayor valor.
Vamos a visualizar los resultados para XGBoost.
# Let's look again at the performance for all models:
apply(test_results[-1], 2, function(x) cor(x,test_results$price)^2)
## frw brw leap ridge enet
## 7.570287e-01 7.579709e-01 7.607211e-01 7.797715e-01 7.497623e-01
## pcr pls rf xgb
## 4.555277e-01 7.500687e-01 9.358482e-07 1.367145e-05
apply(test_results[-1], 2, function(x) mean(abs(x - test_results$price)))
## frw brw leap ridge enet pcr pls rf
## 103485.9 103442.7 102911.8 101236.2 110845.2 125817.8 110806.3 243260.1
## xgb
## 287480.4
Arriba podemos ver el R^2 y el MAE de todos los modelos que hemos probado. Vemos que el peor es claramente el PCR, mientras que el mejor no está del todo caro, pues la mayoría alcanzan resultados bastante similares. En términos de \(R^2\) parece que el mejor es XGBoost. Random Forest no funciona demasiado bien para este problema, ya que queda muy por debajo de modelos como Ridge o la Elastic Net.
La correlación es bastante alta entre modelos, lo cual es negativo a la hora de juntarlos, debido a que los Ensemble Models se benefician precisamente de la diversidad de los modelos, si todos los modelos tienen errores parecidos con respecto al precio, es difícil que un método de ensemble learning pueda predecir mejor que ellos individualmente teniéndolos a todos en cuenta. Podríamos también simplemente hacer la media de las predicciones y ver cuánto nos reportaría eso de error…
test_results$media <- rowMeans(test_results[, -1])
cor(test_results$media,test_results$price)^2
## [1] 0.7356881
Como vemos, no mejora, de hecho empeora con respecto a utilizar sólo el Ridge por ejemplo.
Ahora vamos a encargarnos de los intervalos de confianza de un modelo simple lineal con todas las variables, para hacer algunas comprobaciones finales.
## fit lwr upr
## 3 322923.1 217722.8 478954.5
## 5 452839.7 305372.7 671519.9
## 7 226140.0 152499.6 335340.6
## 12 399230.7 269240.5 591980.4
## 19 195747.6 131995.6 290290.8
## 20 224986.7 151733.1 333605.8
## [1] 0.09419116
## [1] 278464.7 321203.0 820425.6 286041.0 385201.4 426059.2
Tan sólo el 9.7% de las predicciones no contienen el valor real en su intervalo de confianza. Vemos que las predicciones son bastante asimétricas… Esto podría ser bueno a la hora de combinarlo con otro modelo que tuviera otro tipo de sesgo.
Vamos a probar finalmente a computar los intervalos de confianza de las predicciones de otra forma, mostrando en última instancia el gráfico en el que, según estos cálculos, se aprecian las casas que están realmente dentro del intervalo de predicciones y las que están fuera. Como veremos, este método no paramétrico calcula unos intervalos de confianza para las predicciones más estrechos, por lo que más casas quedarían “mal estimadas”, en comparación con el método anterior, paramétrico.
## [1] 0.3219616
Vemos que en este caso se quedarian fuera el 43% de las casas. Los intervalos calculados de esta forma son mucho más exigentes… Lo que parece que está claro es que los precios de las casas no se distribuyen de forma tan lineal ni al pasarnos a logaritmo, y es que cuanto más subes en la escala de los precios de casa, más alto es el escalón; esto el modelo no lo capta, pues como vemos las predicciones que hace son en general más bajas que el valor real.